﻿using System;
using System.ComponentModel;
using System.Windows.Controls;

namespace System.Data 
{
    /// <summary>
    /// Base class for generated DTO
    /// </summary>
    public class BindableObject : INotifyPropertyChanged
    {
        #region Data Fields
        /// <summary>
        /// Holds reference to DataRow instance
        /// </summary>
        private DataRow _dataRow;
        #endregion

        #region Events
        /// <summary>
        /// Delete from collection request
        /// </summary>
        internal event EventHandler<EventArgs> DeleteFromCollection;

        /// <summary>
        /// INotifyPropertyChanged interface implementation
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Remove from collection request
        /// </summary>
        internal event EventHandler<EventArgs> RemoveFromCollection;
        #endregion

        #region Constructors
        /// <summary>
        /// Used for DTO inheritance
        /// </summary>
        /// <param name="dataRow">DataRow instance</param>
        public BindableObject(DataRow dataRow)
        {
            // Validate argument
            if (dataRow == null)
            {
                throw new ArgumentNullException("dataRow");
            }

            this._dataRow = dataRow;
            this._dataRow.PropertyChanged += new PropertyChangedEventHandler(DataRow_PropertyChanged);
        }
        #endregion

        #region Methods
        /// <summary>
        /// Gets caption of specified column
        /// </summary>
        /// <param name="columnName">Column name</param>
        /// <returns>Column caption</returns>
        public string GetDataColumnCaption(string columnName)
        {
            return this._dataRow.Table.Columns[columnName].Caption;
        }

        /// <summary>
        /// Gets DataGridTextColumn instance
        /// </summary>
        /// <param name="columnName">Column name</param>
        /// <returns>DataGridTextColumn instance</returns>
        //public DataGridTextColumn GetDataGridTextColumn(string columnName)
        //{
        //    return this._dataRow.Table.Columns[columnName].DataGridTextColumn;
        //}

        /// <summary>
        /// Gets Selected flag
        /// </summary>
        /// <returns>True if underlied DataRow is selected, otherwise False</returns>
        internal bool GetSelected()
        {
            return this._dataRow.Selected;
        }

        /// <summary>
        /// Gets field error
        /// </summary>
        /// <param name="columnName">Column name</param>
        /// <returns>Field error</returns>
        protected string GetError(string columnName)
        {
            return this._dataRow.ItemArray[columnName].FieldError;
        }

        /// <summary>
        /// Gets "HasError" flag value
        /// </summary>
        /// <param name="columnName">Column name</param>
        /// <returns>True if column has error</returns>
        protected bool GetHasError(string columnName)
        {
            return this._dataRow.ItemArray[columnName].HasError;
        }

        /// <summary>
        /// Gets "HasNoErrors" flag value
        /// </summary>
        /// <param name="columnName">Column name</param>
        /// <returns>True if column has no error</returns>
        protected bool GetHasNoErrors(string columnName)
        {
            return this._dataRow.HasNoErrors;
        }

        /// <summary>
        /// Gets null value from specified DataColumn
        /// </summary>
        /// <param name="columnName">Column name</param>
        protected string GetDataSourceNullValue(string columnName)
        {
            return this._dataRow.Table.Columns[columnName].NullValue;
        }

        /// <summary>
        /// Gets "Required" flag value
        /// </summary>
        /// <param name="columnName">Column name</param>
        /// <returns>True if column is required</returns>
        protected bool GetRequired(string columnName)
        {
            return !this._dataRow.Table.Columns[columnName].AllowDBNull;
        }

        /// <summary>
        /// Gets value from specified field
        /// </summary>
        /// <param name="columnName">Column name</param>
        /// <returns>Field value</returns>
        public string GetValue(string columnName)
        {
            return this._dataRow[columnName] != null ? this._dataRow[columnName].ToString() : null;
        }


        public string GetValue(int index)
        {
            if (index < 0 && index >= this._dataRow.ItemArray.Count)
            {
                throw new Exception("Index Out of Range");
            }
            return this._dataRow[index] != null ? this._dataRow[index].ToString() : null;
        }

        /// <summary>
        /// Bubbles PropertyChanged event
        /// </summary>
        /// <param name="sender">Event source</param>
        /// <param name="e">Event arguments</param>
        private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(sender, e);
            }
        }

        /// <summary>
        /// Rejects changes done on bindable data object
        /// </summary>
        public void RejectChanges()
        {
            this._dataRow.RejectChanges();
        }

        /// <summary>
        /// Sets bindable data object into Deleted state
        /// </summary>
        public void SetDeleted()
        {
            this._dataRow.Delete();
            if (this._dataRow.State == DataRowState.Added)
            {
                if (RemoveFromCollection != null)
                {
                    RemoveFromCollection(this, new EventArgs());
                }
            }
        }

        /// <summary>
        /// Sets bindable data object into Modified state
        /// </summary>
        public void SetModified()
        {
            this._dataRow.SetModified();
        }

        /// <summary>
        /// Sets null value into specified DataColumn
        /// </summary>
        /// <param name="columnName">Column name</param>
        /// <param name="value">Field value</param>
        protected void SetDataSourceNullValue(string columnName, string value)
        {
            this._dataRow.Table.Columns[columnName].NullValue = value;
        }

        /// <summary>
        /// Changes underlined DataRow selection state
        /// </summary>
        /// <param name="selected">True for selecting DataRow, otherwise false</param>
        public void SetSelected(bool selected)
        {
            this._dataRow.Selected = selected;
        }

        /// <summary>
        /// Sets value into specified field
        /// </summary>
        /// <param name="columnName">Column name</param>
        /// <param name="value">Field value</param>
        public void SetValue(string columnName, string value)
        {
            this._dataRow[columnName] = value;
        }

        public void SetValue(int columnIndex, string value)
        {
            this._dataRow[columnIndex] = value;
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Handles DataRow.PropertyChanged event
        /// </summary>
        /// <param name="sender">Event source</param>
        /// <param name="e">Event arguments</param>
        void DataRow_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            this.OnPropertyChanged(sender, e);
        }
        #endregion
    }
}
